# Title: Encontrar los primeros 500 numeros primos
# Autho: Laguna Hernandez Biridiana 14210508
# Description: 500 Numeros primos
# Input:-
# Output: 500 Numero primos


@ 500NumPrimos.s
@ Encontrar y imprimir los primeros 500 numeros primos
@ Basado en Knuth TAOCP vol. 1 147ff
@ He utilizado las etiquetas y os usos de las variables de Knuth, hasta cierto punto.

@@@@@@@@@@
@ registros @
@@@@@@@@@@

@ r1 apuntar a direcciones de "primos"
@ r3 numero que estamos revisando     ( N e Knuth)
@ r4 recuento de primos               ( J en Knuth)
@ r5 divisores que estamos revisando
@ r6 indice para los divisores principales
@ r7 contendra recordatorio           ( R en Knuth)
@ r8 mantendra el cociente            ( Q en Knuth)
@ r9 numeros de primos buscados.

.section           .bss
.comm primo, 200             @ Espacio de reserva para los primos


.section          .data
scp:                      @ Espacio de primos con tres espacios
        .ascii "  "
len = . - spc 
nl:                       @ Solo una nueva linea
        .ascii "\n"
limit:                    @  Indice de la ultima linea que necesitamos  
        .long 500
        
.section .text
.globl _start
_start:


P1:                       @ La creacion de 
ldr r1, =prime            @ r1 puntos de los primos
mov r0, $2                @ Primera prima es 2
str r0, [r1]              @ Almacenar esta cantidad de los primos
ldr r0, =limit            
ldr r9, [r0]              @ r2 Ejerce una serie de bonificaciones para encontrar
mov r3, $3                @ Inicializar N a 3 
mov r4, $1                @ Inicializar J a 1

P2:                       @ Venimos aqui cuando hermos encontrado un primo
add r4, r4, $1            @ Incrementa J
str r3, [r1, #4]!         @ Almacene N en primo (con retroceso)

P3:
cmp r4, r9                @ Comprueba si hemos terminado
bge P9                    @ Si es asi p9

P4:
add r3, r3, $2            @ Agregar 2 a N

P5:                       @ Comienza a revisar los divisores
ldr r6, =prime            @ Copiar el puntero al inicio de la prima
ldr r5, [r6]              @ Cargar primer divisor
mov r7, r3                @ Copia N en R
mov r8, $0                @ Inicializar Q

P6:
cmp r7, r5                @ Si R >= divisor
subge r7, r7, r5          @ Resta el divisor de R
addge r8, r8, $1          @ Incrementa Q
bge P6                    @ Repetir
cmp r7, $0                @ Si R == 0 ...
beq P4                    @ N no es primo, asi que intenta lo siguiente N

P7:
cmp r8, r5                @ Comparar Q con divisor
ble P2                    @ Si Q <= divisor, N es primo

P8:
mov r7, r3                @ Restablecer r7 a N
mov r8, $0                @ Restabecer Q
ldr r5, [r6, #4]!         @ Obtener el siguiente divisor
bal P6                    @ Dividir de nuevo

P9:                       
mov r0, $1                @ Elegir stdout
mov r4, $0                @ Utilizar r4 como un contador temporal
mov r5, $0                @ r5 Cuenta el total de impresiones impresas
ldr r6, =prime            @ Puntero a "primo"
ldr r3, [r6]              @ Carga primer primo

printLoop:
bl print_num              @ Llamada de funcion
add r4, $1                @ Agregar uno al contador de la temperatura
add r5, $1                @ Agrega uno al contador
cmp r5, r9                @ Terminamos?
bge exit                  @ Si es asi, salir
cmp r4, $9                @ Despues de 10 primos
bgt newline               @ Imprimir una nueva linea
ble space                 @ agregar espacios


space:                    @ Saltamos aqui si
mov r0, $1                @ Vamos a 
ldr r1, =spc              @ Imprimir espacio
ldr r2, =len
mov r7, $4
svc $0
ldr r3, [r6, #4]!         @ Carga el siguiente primo
bal printLoop             @ Continuar imprimiendo

newLine:                  @ Saltamos aqui si
mov r0, $1                @ Vamos a 
ldr r1, =nl               @ Imprimir una nueva linea
mov r2, $1
mov r7, $4
svc $0
ldr r3, [r6, #4]!         @ Carga el siguiente primo
mov r4, $0                @ Reinicia contador temporal
bal printLoop             @ Continua imprimiendo

@@@@@@@@@@@@@@@@@@@@@@@@
@ print_num function @
@@@@@@@@@@@@@@@@@@@@@@@@


print_num:
        stmfd sp!, {r0-r9, lr}  @ Presiones regs para apilar
        mov r4, $0              @ Establecer el contador de division a cero
        mov r5, $1              @ Establecer contador char a uno
        
loop:                           @ Rutina de division
        cmp r3, $9              
        ble stackPush           @ Si r3 <=9, llamada stackPush
        sub r3, r3, $10         @ Otro, resta 10 de r3
        add r4, r4, $1          @ Agregar uno a div.contador
        bal loop
        
        
        
  stackPush:
        add r5, r5, $1          @
        orr r0, r3, $0x30       @
        stmfd   sp!, {r0}       @
        cmp r4, $0              @
        beq printChars          @
        mov r3, r4              @
        mov r4, $0              @
        bal loop                @
        
  printChars:
        mov r1, sp              @
        mov r0, $1              @
        mov r2, $1              @
        mov r7, $4              @
        svc $0                  @
        subs r5, r5, $1         @
        ble return              @
        ldmfd sp!, {r0}         @
        bal printChars          @
        
  return:      
        ldmfd sp!, {r0-r9, pc}  @
      
  exit:
  mov r0, $1                    @
  ldr r1, =nl
  mov r2, $1
  mov r7, $4
  svc $0
  mov r7, $1                    @
  svc $0
  
  .end
  

